var graph = argument0;
var height = array_height_2d(graph);
var width = array_length_2d(graph, 0);
var seed = argument2;

//Stack<int[]> stack = new Stack<int[]>();
var stack = ds_stack_create();

//Corridor info
//int MAX_CORRIDOR_LENGTH = 7;
var MAX_CORRIDOR_LENGTH = argument1;

//Starting cell
//Random randomGenerator = new Random(seed);
random_set_seed(seed);

//int[] start = new int[] {randomGenerator.Next(height), randomGenerator.Next(width)};
var start = 0;
start[0] = irandom(height - 1);
start[1] = irandom(width  - 1);

//stack.Push(start);
ds_stack_push(stack, start);

graph[start[0], start[1]] = 2;

//Algorithm
//while (stack.Count != 0)
while (ds_stack_size(stack) != 0)
{
    //if (stack.Count >= 2)
    if (ds_stack_size(stack) >= 2)
    {
        //if (randomGenerator.Next(2) == 1)
        if (irandom(1) == 1)
        {
            //int[] k = stack.Pop();
            k = 0;
            k = ds_stack_pop(stack);
            //int[] l = stack.Pop();
            l = 0;
            l = ds_stack_pop(stack);
            //stack.Push(k);
            ds_stack_push(stack, k);
            //stack.Push(l);
            ds_stack_push(stack, l);
        }
    }
    
    //int[] current = stack.Pop();
    var current = 0;
    current = ds_stack_pop(stack);

    //int[] neighbor = new int[] { current[0], current[1] + 1 };
    var neighbor0 = 0;
    neighbor0[0] = current[0];
    neighbor0[1] = current[1] + 1;
    
    //neighbor  -> neighbor0
    if (neighbor0[1] < width)
    {
        //int exposures = 0;
        var exposures = 0;
        if (neighbor0[1] + 1 < width && graph[neighbor0[0], neighbor0[1] + 1] != 0)
        {
            exposures++;
        }
        if (neighbor0[0] - 1 > -1 && graph[neighbor0[0] - 1, neighbor0[1]] != 0)
        {
            exposures++;
        }
        if (neighbor0[1] - 1 > -1 && graph[neighbor0[0], neighbor0[1] - 1] != 0)
        {
            exposures++;
        }
        if (neighbor0[0] + 1 < height && graph[neighbor0[0] + 1, neighbor0[1]] != 0)
        {
            exposures++;
        }
        if (exposures == 1 && getCorridorLength(graph, neighbor0, 2) < MAX_CORRIDOR_LENGTH)
        {
            graph[neighbor0[0], neighbor0[1]] = 1;
            //stack.Push(neighbor0);
            ds_stack_push(stack, neighbor0);
        }
    }

    //neighbor = new int[] { current[0] - 1, current[1] };
    var neighbor1 = 0;
    neighbor1[0] = current[0] - 1;
    neighbor1[1] = current[1];
    
    if (neighbor1[0] > -1)
    {
        //int exposures = 0;
        var exposures = 0;
        if (neighbor1[1] + 1 < width && graph[neighbor1[0], neighbor1[1] + 1] != 0)
        {
            exposures++;
        }
        if (neighbor1[0] - 1 > -1 && graph[neighbor1[0] - 1, neighbor1[1]] != 0)
        {
            exposures++;
        }
        if (neighbor1[1] - 1 > -1 && graph[neighbor1[0], neighbor1[1] - 1] != 0)
        {
            exposures++;
        }
        if (neighbor1[0] + 1 < height && graph[neighbor1[0] + 1, neighbor1[1]] != 0)
        {
            exposures++;
        }
        if (exposures == 1 && getCorridorLength(graph, neighbor1, 3) < MAX_CORRIDOR_LENGTH)
        {
            graph[neighbor1[0], neighbor1[1]] = 1;
            //stack.Push(neighbor1);
            ds_stack_push(stack, neighbor1);
        }
    }

    //neighbor = new int[] { current[0], current[1] - 1 };
    var neighbor2 = 0;
    neighbor2[0] = current[0];
    neighbor2[1] = current[1] - 1;
    
    if (neighbor2[1] > -1)
    {
        //int exposures = 0;
        var exposures = 0;
        if (neighbor2[1] + 1 < width && graph[neighbor2[0], neighbor2[1] + 1] != 0)
        {
            exposures++;
        }
        if (neighbor2[0] - 1 > -1 && graph[neighbor2[0] - 1, neighbor2[1]] != 0)
        {
            exposures++;
        }
        if (neighbor2[1] - 1 > -1 && graph[neighbor2[0], neighbor2[1] - 1] != 0)
        {
            exposures++;
        }
        if (neighbor2[0] + 1 < height && graph[neighbor2[0] + 1, neighbor2[1]] != 0)
        {
            exposures++;
        }
        if (exposures == 1 && getCorridorLength(graph, neighbor2, 0) < MAX_CORRIDOR_LENGTH)
        {
            graph[neighbor2[0], neighbor2[1]] = 1;
            //stack.Push(neighbor);
            ds_stack_push(stack, neighbor2);
        }
    }

    //neighbor = new int[] { current[0] + 1, current[1] };
    var neighbor3 = 0;
    neighbor3[0] = current[0] + 1;
    neighbor3[1] = current[1];
    
    if (neighbor3[0] < height)
    {
        //int exposures = 0;
        var exposures = 0;
        if (neighbor3[1] + 1 < width && graph[neighbor3[0], neighbor3[1] + 1] != 0)
        {
            exposures++;
        }
        if (neighbor3[0] - 1 > -1 && graph[neighbor3[0] - 1, neighbor3[1]] != 0)
        {
            exposures++;
        }
        if (neighbor3[1] - 1 > -1 && graph[neighbor3[0], neighbor3[1] - 1] != 0)
        {
            exposures++;
        }
        if (neighbor3[0] + 1 < height && graph[neighbor3[0] + 1, neighbor3[1]] != 0)
        {
            exposures++;
        }
        if (exposures == 1 && getCorridorLength(graph, neighbor3, 1) < MAX_CORRIDOR_LENGTH)
        {
            graph[neighbor3[0], neighbor3[1]] = 1;
            //stack.Push(neighbor);
            ds_stack_push(stack, neighbor3);
        }
    }
}
ds_stack_destroy(stack);
return graph;
